package com.lovecanon.jzjl.common;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@Service
public class BaseService {


        public static final String BEAN_NAME = "baseService";
        protected final static String CREATED_SUCCESS = "创建成功";
        protected final static String UPDATE_SUCCESS = "更新成功";
        protected final static String DELETE_SUCCESS = "删除成功";
        protected final static String OPER_SUCCESS = "操作成功";
        protected final static String CREATED_FAILURE = "创建失败";
        protected final static String UPDATE_FAILURE = "更新失败";
        protected final static String DELETE_FAILURE = "删除失败";
        protected final static String OPER_FAILURE = "操作失败";

        @PersistenceContext
        EntityManager entityManager;


        @Resource(name = "jdbcTemplate")
        private JdbcTemplate jdbcTemplate;


        public EntityManager getEm() {
            return this.entityManager;
        }

        public JdbcTemplate getJdbcTemplate() {
            return jdbcTemplate;
        }

        /**
         * 单事务更新
         *
         * @param entity
         * @return
         * @throws Exception
         */
        public Object updateDependentTx(Object entity) throws Exception {
            Session session = ((Session) entityManager.getDelegate()).getSessionFactory().openSession();
            Transaction trans = null;
            try {
                trans = session.beginTransaction();
                session.update(entity);
                trans.commit();
                trans = null;
            } catch (HibernateException e) {
                if (trans != null) {
                    trans.rollback();
                }
                throw e;
            } finally {
                session.close();
            }
            return entity;
        }

        /**
         * 更新对象
         *
         * @param entity
         * @return
         */
        public Object update(Object entity) throws Exception {
            getEm().merge(entity);
            getEm().flush();
            return entity;
        }

        /**
         * 保存对象
         *
         * @param entity
         */
        public Object save(Object entity) throws Exception {
            getEm().persist(entity);
            getEm().flush();
            return entity;
        }

        /**
         * 单事务保存
         *
         * @param entity
         * @return
         * @throws Exception
         */
        public Object saveDependentTx(Object entity) throws Exception {
            Session session = ((Session) entityManager.getDelegate()).getSessionFactory().openSession();
            Transaction trans = null;
            try {
                trans = session.beginTransaction();
                session.save(entity);
                trans.commit();
                trans = null;
            } catch (HibernateException e) {
                if (trans != null) {
                    trans.rollback();
                }
                throw e;
            } finally {
                session.close();
            }
            return entity;
        }

        /**
         * 根据主键查询对象
         *
         * @param beanClass
         * @param key
         * @return
         */
        public <T> Object find(T beanClass, Object key) throws Exception {
            return getEm().find((Class<T>) beanClass, key);
        }


        /**
         * 删除对象
         *
         * @param entity
         */
        public void remove(Object entity) throws Exception {
            getEm().remove(getEm().merge(entity));
            getEm().flush();
        }

        /**
         * 批量保存对象
         *
         * @param entitysToSave
         */
        public void batchSave(final List entitysToSave) throws Exception {
            if (CollectionUtils.isEmpty(entitysToSave)) {
                return;
            }
            int max = entitysToSave.size();
            for (int i = 0; i < max; i++) {
                getEm().persist(entitysToSave.get(i));
                if (i != 0 && i % 10 == 0 || i == max - 1) {
                    getEm().flush();
                }
            }
        }

        /**
         * 批量更新对象
         *
         * @param entitysToMerge
         */
        public void batchUpdate(final List entitysToMerge) throws Exception {
            if (CollectionUtils.isEmpty(entitysToMerge)) {
                return;
            }
            int max = entitysToMerge.size();
            for (int i = 0; i < max; i++) {
                getEm().merge(entitysToMerge.get(i));
                if (i != 0 && i % 10 == 0 || i == max - 1) {
                    getEm().flush();
                }
            }
        }

        /**
         * 批量删除对象
         *
         * @param entitysToDelete
         */
        public void batchRemove(List entitysToDelete) throws Exception {
            if (CollectionUtils.isEmpty(entitysToDelete)) {
                return;
            }
            int max = entitysToDelete.size();
            for (int i = 0; i < max; i++) {
                getEm().remove(entitysToDelete.get(i));
                if (i != 0 && i % 10 == 0 || i == max - 1) {
                    getEm().flush();
                }
            }
        }

        /**
         * 查询对象并返回对象集合
         *
         * @param entityClass
         * @return
         */
        public List finaAll(Class entityClass) throws Exception {
            String queryString = buildQueryString(entityClass, null);
            Query query = getEm().createQuery(queryString);
            return query.getResultList();
        }

        /**
         * 根据字段查询对象集合
         *
         * @param entityClass
         * @param field
         * @param value
         * @return
         */
        public List findListByField(Class entityClass, String field, Object value) throws Exception {
            String queryString = buildQueryString(entityClass, new String[]{field});
            Query query = getEm().createQuery(queryString);
            if (!StringUtils.isEmpty(field)) {
                query.setParameter(1, value);
            }
            return query.getResultList();
        }

        /**
         * 根据字段查询对象
         *
         * @param entityClass
         * @param params
         * @return
         */
        public Object findObjectByFields(Class entityClass, Map params) throws Exception {
            String queryString = buildQueryStringWithNamedParams(entityClass, params);
            Query query = getEm().createQuery(queryString);
            Iterator<Map.Entry<String, Object>> iterator = params.entrySet().iterator();
            Map.Entry<String, Object> entry = null;
            while (iterator.hasNext()) {
                entry = iterator.next();
                query.setParameter(entry.getKey(), entry.getValue());
            }
            int resultSize = query.getResultList().size();
            if (resultSize > 0) {
                return query.getSingleResult();
            } else {
                return null;
            }
        }

        /**
         * 根据字段查询单个对象
         *
         * @param entityClass
         * @param field
         * @param value
         * @return
         */
        public Object findObjectByField(Class entityClass, String field, Object value) throws Exception {
            String queryString = buildQueryString(entityClass, new String[]{field});
            Query query = getEm().createQuery(queryString);
            if (!StringUtils.isEmpty(field)) {
                query.setParameter(1, value);
            }
            Object obj;
            try {
                obj = query.getSingleResult();
            } catch (Exception e) {
                obj = null;
            }
            return obj;
        }

        /**
         * 根据类字段获得结果集（支持分页）
         *
         * @param entityClass
         * @param field
         * @param value
         * @param start
         * @param maxRows
         * @return
         * @throws DataAccessException
         */
        public List findListByField(Class entityClass, String field, Object value, int start, int maxRows) throws Exception {
            String queryString = buildQueryString(entityClass, new String[]{field});
            Query query = getEm().createQuery(queryString);
            query.setParameter(1, value);
            if (maxRows >= 0) {
                query.setMaxResults(maxRows);
            }
            if (start >= 0) {
                query.setFirstResult(start);
            }
            return query.getResultList();
        }

        /**
         * 根据字段和分页器查询符合条件的记录集
         *
         * @param entityClass
         * @param params
         * @param dgm
         * @return
         */
        public DataGridResultModel findPaginated(Class entityClass, Map params, DataGridModel dgm) throws Exception {
            int maxRows = dgm.getLimit();
            int start = dgm.getOffset();
            String queryString = buildQueryStringWithNamedParams(entityClass, params);
            Query query = getEm().createQuery(queryString);
            Iterator<Map.Entry<String, Object>> iterator = params.entrySet().iterator();
            Map.Entry<String, Object> entry = null;
            while (iterator.hasNext()) {
                entry = iterator.next();
                query.setParameter(entry.getKey(), entry.getValue());
            }
            if (maxRows >= 0) {
                query.setMaxResults(maxRows);
            }
            if (start >= 0) {
                query.setFirstResult(start);
            }
            List results = query.getResultList();
            long resultSize = 0L;
            if (results != null && results.size() > 0) {
                resultSize = countByFields(entityClass, params);
            }
            DataGridResultModel resultModel = new DataGridResultModel();
            resultModel.setRows(results);
            resultModel.setTotal(resultSize);
            return resultModel;
        }

        /**
         * 根据字段查询符合条件的记录集（支持分页）
         *
         * @param entityClass
         * @param params
         * @param start
         * @param maxRows
         * @return
         */
        public <T> List findListByFields(Class entityClass, Map params, int start, int maxRows) throws Exception {
            String queryString = buildQueryStringWithNamedParams(entityClass, params);
            Query query = getEm().createQuery(queryString);
            Iterator<Map.Entry<String, Object>> iterator = params.entrySet().iterator();
            Map.Entry<String, Object> entry = null;
            while (iterator.hasNext()) {
                entry = iterator.next();
                query.setParameter(entry.getKey(), entry.getValue());
            }
            if (maxRows >= 0) {
                query.setMaxResults(maxRows);
            }
            if (start >= 0) {
                query.setFirstResult(start);
            }
            return query.getResultList();
        }

        /**
         * 根据字段查询符合条件的记录集
         *

         */
        public <T> List findListByFields(Class entityClass, Map params) throws Exception {
            String queryString = buildQueryStringWithNamedParams(entityClass, params);
            Query query = getEm().createQuery(queryString);
            Iterator<Map.Entry<String, Object>> iterator = params.entrySet().iterator();
            Map.Entry<String, Object> entry = null;
            while (iterator.hasNext()) {
                entry = iterator.next();
                query.setParameter(entry.getKey(), entry.getValue());
            }
            return query.getResultList();
        }

        /**
         * 获得记录数
         *
         * @param entityClass
         * @param params
         * @return
         */
        public Integer countByFields(Class entityClass, Map params) throws Exception {
            String queryString = "select count(*) ";
            queryString += buildQueryStringWithNamedParams(entityClass, params);
            Query query = getEm().createQuery(queryString);
            Iterator<Map.Entry<String, Object>> iterator = params.entrySet().iterator();
            Map.Entry<String, Object> entry = null;
            while (iterator.hasNext()) {
                entry = iterator.next();
                query.setParameter(entry.getKey(), entry.getValue());
            }
            Number result = (Number) query.getSingleResult();
            return result.intValue();
        }

        /**
         * 通过数组字段集构建HQL语句
         *
         * @param entityClass
         * @param fields
         * @return
         */
        private String buildQueryString(Class entityClass, String fields[]) throws Exception {
            StringBuilder queryBuilder = new StringBuilder();
            queryBuilder.append("from ").append(entityClass.getName());
            if (fields != null && fields.length > 0) {
                queryBuilder.append(" where ");
                String as[];
                int j = (as = fields).length;
                for (int i = 0; i < j; i++) {
                    String field = as[i];
                    queryBuilder.append(field).append(" = ? and ");
                }

                if (queryBuilder.lastIndexOf(" and ") == queryBuilder.length() - 5) {
                    queryBuilder.delete(queryBuilder.length() - 5, queryBuilder.length());
                }
            }
            return queryBuilder.toString();
        }

        /**
         * 通过Map字段集构建HQL语句
         *
         * @param entityClass
         * @param params
         * @return
         */
        private <T> String buildQueryStringWithNamedParams(Class entityClass, Map params) throws Exception {
            StringBuilder queryBuilder = new StringBuilder();
            queryBuilder.append("from ").append(entityClass.getName());
            if (!CollectionUtils.isEmpty(params)) {
                queryBuilder.append(" where ");
                Map.Entry entry;
                Iterator iterator = params.entrySet().iterator();
                while (iterator.hasNext()) {
                    entry = (Map.Entry) iterator.next();
                    if (entry.getKey() != null) {
                        queryBuilder.append((String) entry.getKey()).append(" = :").append((String) entry.getKey())
                                .append(" and ");
                    }
                }

                if (queryBuilder.lastIndexOf(" and ") == queryBuilder.length() - 5) {
                    queryBuilder.delete(queryBuilder.length() - 5, queryBuilder.length());
                }
            }
            return queryBuilder.toString();
        }

        /**
         * 通过HQL查询结果，并返回结果集
         *
         * @param hql
         * @return list
         */
        public List findListByHql(String hql, DataGridModel dgm) throws Exception {
            int maxRows = dgm.getLimit();
            int start = dgm.getOffset();
            return findListByHql(hql, start, maxRows);
        }

        /**
         * 通过HQL查询结果，并返回结果集
         *
         * @param hql
         * @return list
         */
        public List findListByHql(String hql) throws Exception {
            Query query = this.getEm().createQuery(hql);
            return query.getResultList();
        }

        /**
         * 通过HQL查询结果，并返回结果集
         *
         * @param hql
         * @return list
         */
        public List findListByHql(String hql, int start, int maxRows) throws Exception {
            Query query = this.getEm().createQuery(hql);
            if (maxRows >= 0) {
                query.setMaxResults(maxRows);
            }
            if (start >= 0) {
                query.setFirstResult(start);
            }
            return query.getResultList();
        }

        /**
         * 通过HQL查询结果，并返回结果集
         *
         * @param
         * @return list
         */
        public Long findCountByHql(String hql) throws Exception {
            Query query = this.getEm().createQuery(hql);
            return (Long) query.getSingleResult();
        }

        /**
         * 通过HQL执行结果，并返回处理数
         *
         * @param hql
         * @return int
         */
        public int updateExecute(String hql) {
            Query query = this.getEm().createQuery(hql);
            return query.executeUpdate();
        }


    }
